package org.zjvis.datascience.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.io.IOException;
import java.util.HashMap;
import okhttp3.Response;
import org.apache.groovy.util.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.zjvis.datascience.common.annotation.CategoryAuth;
import org.zjvis.datascience.common.annotation.ProjectAuth;
import org.zjvis.datascience.common.dto.DatasetAndCategoryDTO;
import org.zjvis.datascience.common.dto.DatasetCategoryDTO;
import org.zjvis.datascience.common.dto.dataset.DatasetNameStatusDTO;
import org.zjvis.datascience.common.dto.kg.KnowledgeGraphDTO;
import org.zjvis.datascience.common.dto.user.UserDTO;
import org.zjvis.datascience.common.enums.ProjectAuthEnum;
import org.zjvis.datascience.common.model.ApiResult;
import org.zjvis.datascience.common.model.ApiResultCode;
import org.zjvis.datascience.common.util.DozerUtil;
import org.zjvis.datascience.common.util.JwtUtil;
import org.zjvis.datascience.common.vo.category.*;
import org.zjvis.datascience.common.vo.project.ProjectIdVO;
import org.zjvis.datascience.service.DatasetCategoryService;
import org.zjvis.datascience.service.kg.KnowledgeGraphService;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description 分类管理接口 Controller
 * @date 2021-12-23
 */
@Api(tags = "分类管理")
@RestController
@RequestMapping("/category")
public class DatasetCategoryController {

    private static final Map<String, String> typeMaps = Maps.of(
            "data","csv,excel,pipeline,http,table",
            "gis","gis,gis-excel,gis-csv",
            "graph","graph-json,graph-excel,graph-gml",
            "kg","owl,kg-json"
    );

    @Autowired
    DatasetCategoryService datasetCategoryService;

    @Autowired
    private KnowledgeGraphService knowledgeGraphService;

    @PostMapping("/queryCurrentUserDatasetCategory")
    @ApiOperation(value = "获取当前用户分类目录及数据集")
    public ApiResult<List<DatasetAndCategoryVO>> queryCurrentUserDatasetCategory() {
        List<DatasetAndCategoryVO> res = datasetCategoryService
                .queryDatasetAndCategoryByUserId(JwtUtil.getCurrentUserId());
        return ApiResult.valueOf(res);
    }

    @PostMapping("/queryCurrentUserCategory")
    @ApiOperation(value = "获取当前用户的分类目录")
    public ApiResult<List<DatasetCategoryDTO>> queryCurrentUserCategory() {
        UserDTO user = JwtUtil.getCurrentUserDTO();

        List<DatasetCategoryDTO> res = datasetCategoryService.queryByUserId(user.getId());
        return ApiResult.valueOf(res);
    }

    @PostMapping("/queryDatasetCategoryByProjectId")
    @ApiOperation(value = "根据项目id获取当前用户分类目录及数据集及其状态")
    public ApiResult<List<DatasetAndCategoryForProjectVO>> queryDatasetCategoryByProjectId(
            @ProjectAuth(auth = ProjectAuthEnum.READ) @Valid @RequestBody SearchDatasetAndCategoryVO pv)
        throws IOException {
        if (typeMaps.containsKey(pv.getType())) {
            if (pv.getType().equals("kg")){//KG没有统一  手动伪造格式返回
                List<DatasetAndCategoryDTO> datasetAndCategoryDTOList =
                    datasetCategoryService.queryKGFileByUserId(JwtUtil.getCurrentUserId());
                DatasetAndCategoryForProjectVO kgDummyResult = DatasetAndCategoryForProjectVO.builder().categoryName("我的KG文件").build();
                kgDummyResult.setDataset(
                    datasetAndCategoryDTOList.stream()
                        .map(
                            datasetAndCategoryDTO -> {
                                return DatasetNameStatusDTO.builder()
                                    .id(datasetAndCategoryDTO.getDatasetId())
                                    .name(datasetAndCategoryDTO.getDatasetName())
                                    .type("kg")
                                    .status(0)
                                    .build();
                            }
                        )
                        .collect(Collectors.toList()));
                return ApiResult.valueOf(Lists.newArrayList(kgDummyResult));
            }else {
                pv.setType(typeMaps.get(pv.getType()));
                return ApiResult.valueOf(datasetCategoryService.queryDatasetCategoryByProjectId(pv));
            }
        }else {
            return ApiResult.error(ApiResultCode.DATA_TYPE_NOT_FOUND);
        }
    }

    /**
     * 用 queryDatasetCategoryByProjectId 可实现全部功能
     * @param vo
     * @return
     */
    @Deprecated
    @PostMapping("/searchInProject")
    @ApiOperation(value = "项目中检索数据集")
    public ApiResult<List<DatasetAndCategoryForProjectVO>> searchInProject(
            @ProjectAuth(auth = ProjectAuthEnum.READ) @Valid @RequestBody SearchDatasetAndCategoryVO vo) {
        List<DatasetAndCategoryForProjectVO> res = datasetCategoryService.searchInProject(vo);
        return ApiResult.valueOf(res);
    }

    @PostMapping(value = "/save")
    @ResponseBody
    @ApiOperation(value = "创建数据集分类目录")
    public ApiResult<Long> save(@Valid @RequestBody CreateDatasetCategoryVO dcVO) {
        UserDTO user = JwtUtil.getCurrentUserDTO();
        DatasetCategoryDTO dcDTO = DozerUtil.mapper(dcVO, DatasetCategoryDTO.class);
        dcDTO.setUserId(user.getId());
        dcDTO.setGmtCreator(user.getId());
        dcDTO.setGmtModifier(user.getId());
        return ApiResult.valueOf(datasetCategoryService.save(dcDTO));
    }

    @PostMapping(value = "/update")
    @ResponseBody
    @ApiOperation(value = "修改数据集分类目录")
    public ApiResult<Boolean> update(@CategoryAuth() @RequestBody UpdateDatasetCategoryVO dcVO) {
        DatasetCategoryDTO dcDTO = DozerUtil.mapper(dcVO, DatasetCategoryDTO.class);
        dcDTO.setUserId(JwtUtil.getCurrentUserId());
        dcDTO.setGmtCreator(JwtUtil.getCurrentUserId());
        dcDTO.setGmtModifier(JwtUtil.getCurrentUserId());
        dcDTO.setGmtModify(LocalDateTime.now());
        return ApiResult.valueOf(datasetCategoryService.update(dcDTO));
    }

    @PostMapping(value = "/delete")
    @ResponseBody
    @ApiOperation(value = "删除数据集分类目录")
    public ApiResult<Boolean> delete(@CategoryAuth() @RequestBody DeleteDatasetCategoryVO dcVO)
            throws Exception {
        //物理删除，只有当前用户为userId才能删除
        UserDTO user = JwtUtil.getCurrentUserDTO();
        DatasetCategoryDTO dcDTO = DozerUtil.mapper(dcVO, DatasetCategoryDTO.class);
        dcDTO.setUserId(user.getId());
        Map<String, String> kgRequestParams = new HashMap<>();
        kgRequestParams.put("userId", String.valueOf(user.getId()));
        kgRequestParams.put("category", String.valueOf(dcVO.getId()));
        Response response = knowledgeGraphService.queryNebula(kgRequestParams, "deleteByCategoryId");
        if (response != null && response.code() == 200) {
            String str = response.body().string();
            ObjectMapper mapper = new ObjectMapper();
            JsonNode responseNode = mapper.readTree(str);
            if (responseNode.has("code")
                && responseNode.get("code").asInt() != 200
                && responseNode.has("message")) {
                return ApiResult.valueOf(ApiResultCode.SYS_ERROR, Boolean.FALSE,
                    responseNode.get("message").toString());
            }
        }
        JSONObject res = datasetCategoryService.delete(dcDTO);
        if (res.getInteger("error") == 1) {
            return ApiResult.valueOf(ApiResultCode.SYS_ERROR, Boolean.FALSE, "该分类下数据集：" + res.getString("datasetNames") + "已被加载到项目中，请先从项目中移出再删除!");
        } else {
            return ApiResult.valueOf(res.getBoolean("result"));
        }
    }
}
